﻿#include<iostream>
#include<assert.h>
using namespace std;

// 日期类
class Date
{
public:
	int GetMonthDay(int year, int month)
	{
		// static修饰放在静态区 不用每次调用都创建
		static int monthDayArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		// 判断闰年
		if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
		{
			return 29;
		}
		else
		{
			return monthDayArray[month];
		}
	}
	// 构造函数
	Date(int year = 2000, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
		// 检查日期的合法性
		if(!(year >= 1 
			&& (month >= 1 && month <= 12)
			&& (day >= 1 && day <= GetMonthDay(year, month))))
		{
			cout << "非法日期" << _year << "-" << _month << "-" << _day << endl;
		}
	}
	// 拷贝构造
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	// 运算符重载的意义：可读性
	// 注意：
	// 1.重载操作符必须有一个类类型参数 （只针对自定义类型）
	// 2.用于内置类型的运算符，其含义不能改变，例如：内置的整型+，不能改变其含义
	// 3.作为类成员函数重载时，其形参看起来比操作数数目少1，因为成员函数的第一个参数为隐藏的this指针
	// 4.不能重载的5个运算符：⑴ .*（不常见也不常用）  ⑵ ::    ⑶sizeof  ⑷? : （三目运算符） ⑸​​​​​​​​​​​​​​ .
	// 赋值运算符重载
	// 形参的顺序：this就是左操作数 d是右操作数 不能交换
	// 传参可以使用传值传参，只不过多调用一次拷贝构造函数 不存在死递归
	// 传值传参和传值返回都会调用一次拷贝构造
	Date& operator=(const Date& d)
	{
		_year = d._day;
		_month = d._month;
		_day = d._day;

		// 赋值返回左操作数 以支持链式赋值
		// *this ==> d1 出了作用域还在 可以引用返回
		// 返回 d 存在的问题：权限的放大
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};
// 栈类
class Stack
{
public:
	// 构造函数
	Stack(int capacity = 4) {
		_a = (int*)malloc(sizeof(int) * capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capacity = capacity;
	}
	// 拷贝构造函数 深拷贝
	Stack(const Stack& st) {
		cout << "stack的拷贝构造函数" << endl;
		_a = (int*)malloc(sizeof(int) * st._capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		memcpy(_a, st._a, sizeof(int) * st._top);
	}
	// 赋值运算符重载（和拷贝构造函数具有相似的性质）
	// 不显示定义会默认生成 对自定义类型和内置类型都会处理 进行值拷贝
	// st1 = st2
	Stack& operator=(const Stack& st)
	{
		// st1 = st1 
		// 两个不同的栈才执行
		if (this != &st)
		{
			// 重新分配空间
			free(_a);
			_a = (int*)malloc(sizeof(int) * st._capacity);
			if (_a == nullptr)
			{
				perror("malloc fail");
				exit(-1);
			}
			memcpy(_a, st._a, sizeof(int) * st._top);
		}
		return *this;
	}
	void push(int x)
	{
		// 扩容
		_a[_top++] = x;
	}
	// 析构函数
	~Stack()
	{
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	int* _a;
	int _top;
	int _capacity;

};
class myQueue
{
public:
	// 初始化列表
	myQueue(size_t capacity = 8)
		:_popST(8)
		, _pushST(8)
		, _size(0)
	{
		// 初始化
	}
	void push(int x)
	{

	}
private:
	Stack _pushST;
	Stack _popST;
	size_t _size;
};
void tastDate()
{
	Date d1;
	Date d2(2024, 12, 24);
	d1.Print();
	Date d3(d2); // 拷贝构造：初始化一个即将创建的对象
	d1 = d2; // 赋值重载（复制拷贝）：两个已经创建好的对象
	d1.Print();

	Date d4 = d2; // 拷贝构造：初始化一个即将创建的对象
	
	Date d5;
	d1 = d5 = d2; //链式赋值

}
void testStack()
{
	Stack st1;
	st1.push(1);
	st1.push(2);

	Stack st2;
	st2.push(10);
	st2.push(20);
	st2.push(30);

	st1 = st2; // 赋值重载
	// 默认生成的赋值重载函数存在问题：1.析构两次 崩溃 2.内存泄露 st1和st2指向同一块空间 st1原来指向的空间没有释放

}
int main()
{
	Date d1(2024, 12, 35);
	Date d2(2024, 12, 24);
	tastDate();
	return 0;
}